/**
 * @UiSizer.cpp
 * Copyright 2013 (C) FatalEror / Dean Bahari
 * 
 * UiPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * See LICENSE file in main folder for more information.
 */

#include "UiCommon.hpp"
#include "UiBase.hpp"
#include "UiEvent.hpp"
#include "UiSizer.hpp"
#include "UiWindow.hpp"

UiSizer::UiSizer(int type)
{
	mType        = type;
	mCurrentItem = -1;
}

UiSizer::UiSizer(UiBase *holder, int type)
{
	this->setHolder(holder);
	mType        = type;
	mCurrentItem = -1;
}

void UiSizer::setHolder(UiBase *holder)
{
	holder->setSizer(this);
	this->setParent(holder);
	mWidth  = holder->getWidth();
	mHeight = holder->getHeight();
}

void UiSizer::handleResize(int width, int height)
{
	RECT rc = { this->getPosition().x, this->getPosition().y, this->getPosition().x + width, this->getPosition().y + height };

	if (this->mType == UiSizer::UI_SIZER_HORIZONTAL) {
		for (unsigned int i = 0; i < mItem.size(); i++) {
			UiSizerItem *item = &mItem[i];
			if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_RIGHT) {
				item->mRect.right  = rc.right - item->mMargin.right;
				item->mRect.left   = item->mRect.right - item->mWidth;
				item->mRect.top    = rc.top;
				item->mRect.bottom = rc.bottom;
				rc.right = item->mRect.left - item->mMargin.left;
			} else {
				item->mRect.left   = rc.left + item->mMargin.left;
				item->mRect.right  = item->mWidth > 0 ? item->mRect.left + item->mWidth : rc.right - item->mMargin.right;
				item->mRect.top    = rc.top;
				item->mRect.bottom = rc.bottom;
				rc.left = item->mRect.right + item->mMargin.right;
			}
		}

		for (unsigned int i = 0; i < mItem.size(); i++) {
			UiSizerItem *item = &mItem[i];
			if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_MIDDLE) {
				item->mHandle->setPosition(item->mRect.left, (item->mRect.top + item->mRect.bottom - item->mHeight) / 2);
				item->mHandle->setSize(item->mWidth > 0 ? item->mWidth : item->mRect.right - item->mRect.left, item->mHeight);
			} else if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_BOTTOM) {
				item->mHandle->setPosition(item->mRect.left, item->mRect.bottom - item->mHeight - item->mMargin.bottom);
				item->mHandle->setSize(item->mWidth > 0 ? item->mWidth : item->mRect.right - item->mRect.left, item->mHeight);
			} else {
				item->mHandle->setPosition(item->mRect.left, item->mRect.top + item->mMargin.top);
				item->mHandle->setSize(item->mWidth > 0 ? item->mWidth : item->mRect.right - item->mRect.left, item->mHeight > 0 ? item->mHeight : item->mRect.bottom - item->mRect.top - item->mMargin.bottom - item->mMargin.top);
			}
			if (item->mIsSizer)
				reinterpret_cast<UiSizer*>(item->mHandle)->handleResize(item->mHandle->getWidth(), item->mHandle->getHeight());
		}
	} else if (this->mType == UiSizer::UI_SIZER_VERTICAL) {
		for (unsigned int i = 0; i < mItem.size(); i++) {
			UiSizerItem *item = &mItem[i];
			if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_BOTTOM) {
				item->mRect.bottom = rc.bottom - item->mMargin.bottom;
				item->mRect.top    = item->mRect.bottom - item->mHeight;
				item->mRect.left   = rc.left;
				item->mRect.right  = rc.right;
				rc.bottom = item->mRect.top - item->mMargin.top;
			} else {
				item->mRect.top    = rc.top + item->mMargin.top;
				item->mRect.bottom = item->mHeight > 0 ? item->mRect.top + item->mHeight : rc.bottom - item->mMargin.bottom;
				item->mRect.left   = rc.left;
				item->mRect.right  = rc.right;
				rc.top = item->mRect.bottom + item->mMargin.bottom;
			}
		}

		for (unsigned int i = 0; i < mItem.size(); i++) {
			UiSizerItem *item = &mItem[i];
			if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_CENTER) {
				item->mHandle->setPosition((item->mRect.left + item->mRect.right - item->mWidth) / 2, item->mRect.top);
				item->mHandle->setSize(item->mWidth, item->mHeight > 0 ? item->mHeight : item->mRect.bottom - item->mRect.top);
			} else if (item->mAlignType & UiSizer::UI_SIZER_ALIGN_RIGHT) {
				item->mHandle->setPosition(item->mRect.right - item->mWidth - item->mMargin.right, item->mRect.top);
				item->mHandle->setSize(item->mWidth, item->mHeight > 0 ? item->mHeight : item->mRect.bottom - item->mRect.top);
			} else {
				item->mHandle->setPosition(item->mRect.left + item->mMargin.left, item->mRect.top);
				item->mHandle->setSize(item->mWidth > 0 ? item->mWidth : item->mRect.right - item->mRect.left - item->mMargin.right - item->mMargin.left, item->mHeight > 0 ? item->mHeight : item->mRect.bottom - item->mRect.top);
			}
			if (item->mIsSizer)
				reinterpret_cast<UiSizer*>(item->mHandle)->handleResize(item->mHandle->getWidth(), item->mHandle->getHeight());
		}
	}
}

UiSizer &UiSizer::attach(UiSizer *sizer)
{
	sizer->setParent(this->getParent());
	mCurrentItem++;

	UiSizerItem sizerItem;
	ZeroMemory(&sizerItem, sizeof(sizerItem));
	sizerItem.mHandle    = sizer;
	sizerItem.mIsSizer   = true;
	sizerItem.mAlignType = UiSizer::UI_SIZER_ALIGN_LEFT | UiSizer::UI_SIZER_ALIGN_TOP;

	mItem.push_back(sizerItem);

	return (*this);
}

UiSizer &UiSizer::attach(UiBase *item)
{
	this->getParent()->addChild(item);
	ShowWindow(item->getHandle(), SW_SHOW);

	mCurrentItem++;

	UiSizerItem sizerItem;
	ZeroMemory(&sizerItem, sizeof(sizerItem));
	sizerItem.mHandle    = item;
	sizerItem.mAlignType = UiSizer::UI_SIZER_ALIGN_LEFT | UiSizer::UI_SIZER_ALIGN_TOP;

	mItem.push_back(sizerItem);

	return (*this);
}

UiSizer &UiSizer::attach(UiToolWindow *window)
{
	window->mAttached = true;
	return this->attach(reinterpret_cast<UiBase*>(window));
}

UiSizer &UiSizer::setMargin(int left, int top, int right, int bottom)
{
	mItem[mCurrentItem].mMargin.left   = left;
	mItem[mCurrentItem].mMargin.top    = top;
	mItem[mCurrentItem].mMargin.right  = right;
	mItem[mCurrentItem].mMargin.bottom = bottom;

	return (*this);
}

UiSizer &UiSizer::setSize(int width, int height)
{
	mItem[mCurrentItem].mWidth        = width;
	mItem[mCurrentItem].mHeight       = height;

	if (width <= 0) {
		mItem[mCurrentItem].mAlignType = mItem[mCurrentItem].mAlignType & 0xFE;
		mItem[mCurrentItem].mAlignType |= UiSizer::UI_SIZER_ALIGN_LEFT;
	}
	if (height <= 0) {
		mItem[mCurrentItem].mAlignType = mItem[mCurrentItem].mAlignType & 0xEF;
		mItem[mCurrentItem].mAlignType |= UiSizer::UI_SIZER_ALIGN_TOP;
	}

	return (*this);
}

UiSizer &UiSizer::setAlign(int type)
{
	mItem[mCurrentItem].mAlignType = type;

	if (mItem[mCurrentItem].mWidth <= 0) {
		mItem[mCurrentItem].mAlignType = mItem[mCurrentItem].mAlignType & 0xF0;
		mItem[mCurrentItem].mAlignType |= UiSizer::UI_SIZER_ALIGN_LEFT;
	}
	if (mItem[mCurrentItem].mHeight <= 0) {
		mItem[mCurrentItem].mAlignType = mItem[mCurrentItem].mAlignType & 0x0F;
		mItem[mCurrentItem].mAlignType |= UiSizer::UI_SIZER_ALIGN_TOP;
	}

	return (*this);
}